#coding:utf8
'''
------------------------------------------------------------
Description:    
Author:              Simon
Date:                Created on 2019年9月3日
------------------------------------------------------------
'''

import libs.platform_version
import eventlet.wsgi
from flask import Flask, request, current_app, g, render_template
from flask_cors import *
from functools import wraps
from libs.log import L
from libs.redisEx2 import MyRedis as rs
from libs.utils import TM, RandCode, TMSS
from libs.auth_code import create_validate_code
from common.key import KEY
from common.cache_request import RequestCache
from config import Config as C
from common.response import NormalResponseJson, NormalResponse, ErrorResponse, ErrorResponseJson, ErrorResponseData
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer, BadSignature, SignatureExpired

import login as lg 



app = Flask(__name__)
CORS(app, supports_credentials=True)
app.config['SECRET_KEY'] = 'AreUOK'
app.config['TOKEN_EXPIRATION'] = 7200

def get_token(username, level = 0, scope = "1"):
    expiration = current_app.config['TOKEN_EXPIRATION']
    s = Serializer(current_app.config['SECRET_KEY'], expires_in=expiration)
    token = s.dumps({ 'user': username, 'level': level, 'scope': scope })
    return token.decode('ascii')

def verify_password(token):
    s = Serializer(current_app.config['SECRET_KEY'])
    try:
        data = s.loads(token)
    except BadSignature:
        return False, "温馨提示：登录超时，请重新登陆！" # 'token is invalid'
    except SignatureExpired:
        raise (False, 'token is expired')
    '''End try'''
     
    g.user = {'user': data['user'], 'level': data['level'], 'scope': data['scope']}
    return True, "OK"

def authRequired(level):
    def wrapper(func):
        @wraps(func)
        def inner_wrapper(*args, **kwargs):
            R = request.form if request.method=='POST' else request.args
            token, lc = R.get('tk', ''), R.get('lc', '')
            
            '''未提供token'''
            if token=='':
                return ErrorResponseJson("温馨提示：登录超时，请重新登陆！", None, '110') # 116-06
            flag, message = verify_password(token)
            '''token无效'''
            if not flag: 
                user = request.args.get('user', '')
                L.info(user, "auth failed")
                return ErrorResponseJson(message, None, '110')
            '''二次验证'''
            info = rs.hget('TKS', lc)
             
            if not info or info['tk']!=token:
                return ErrorResponseJson("登录超期，请重新登陆!", None, '110')
            
            '''权限检查'''
            U = rs.hget('UserInfo', info['user'])
            if not U or U['level'] < int(level[2:]): return ErrorResponseJson("权限不够或需要重新登陆！")
            
            '''此处可以优化，由装饰器控制返回结果'''
            res = RequestCache(func, info['user'], request, *args, **kwargs)
            return res
        return inner_wrapper
    return wrapper    

@app.route('/webLogin', methods=['GET', 'POST'])    
def webLogin():
    '''第二个参数传1则无需验证码'''
    return webLoginCommon(request, 1)

def webLoginCommon(request, app = None):
    R = request.form if request.method=='POST' else request.args
    securityCode, codeTms = str(R.get('securityCode', '')), str(R.get('tms', ''))
    correctCode = str(rs.hget('securityCode', codeTms))

    '''若app端无需验证码'''
    if not app and (codeTms=='' or securityCode=='' or correctCode!=securityCode): 
        return ErrorResponseJson('验证码有误， 请重新输入！', None, '103-02')
    
    username, password = R.get('username', ''), R.get('password', '')
    ip = ""
    address = "" 
    data = lg.com_login(username, password, ip, address, app)
    if data['error']: return ErrorResponseData(data)
    
    token = get_token(username)
    uKey = str(abs(hash(token)) + 3456)
    
    '''TODO: 定期删除TKS或设置redis过期时间，防止太长'''
    U = data['data']
    userInfo = {'name': username, 'level': U['level'], 'type': U['type'], 'id': U['id']}
    info = rs.hget('Users', uKey)
    if info and info['name'] != username: uKey += RandCode(6)
    rs.hset('TKS', uKey, {'tk': token, 'user': username, 'time': TM()})
    rs.hset('Users', uKey, userInfo)
    rs.hset(KEY.USER_INFO, username, userInfo)

    data = {'tk': token, 'lc': uKey, 'lv': U['level'], 'address': address, "ip": ip, "client": "Win", "loginTime": TMSS() }
    
    return NormalResponseJson(request, data)

'''验证码'''
@app.route('/login-security-code')
def get_code():
    params = request.args.items()
    if len(params)==0: return ''
    tms = params[0][0]
    bufStr, codeStr = create_validate_code()

    response = app.make_response(bufStr)
    response.headers['Content-Type'] = 'image/png'
    '''存储待验证'''
    rs.hset('securityCode', tms, codeStr)

    return response    

'''--------------------------------------业务接口部分------------------------------------------'''
@app.route('/')
def index():
    return "Welcome..."

'''提现管理-操作'''
@app.route('/test', methods=['GET', 'POST'])
@authRequired('lv1')  
def test(user):
    R = request.form if request.method=='POST' else request.args
    status = R.get('status', '')
    if user=='' or status=='': return ErrorResponseJson("请求的参数有误！")
    flag = {'status': status}
    
    return NormalResponseJson(request, flag) 


if __name__ == '__main__':
    '''
    login test: http://localhost:9404/webLogin?username=admin&password=123456
    Interface test: http://localhost:9404/test?status=1&tk=eyJhbG&lc*=1943043233
    Security-code test: http://localhost:9404/login-security-code?1567569328448
    '''
    L.info("Server Start.")
    eventlet.wsgi.server(eventlet.listen(('', C.web.PORT)), app, log_output=False)
    

